using System;

namespace Slaks.Graphs.Algorithms
{
	public class GraphDistances
	{
		public static long GetGraphSizeVertexEdgeCount(Graph graph)
		{
			return (graph.GetVertexCount() + graph.GetEdgeCount());
		}

		/// <summary>
		/// MCS
		/// </summary>
		/// <param name="one"></param>
		/// <param name="two"></param>
		/// <returns></returns>
		public static double DistMCS4VertexEdgeCount(Graph one, Graph two)
		{
			double maxCommonSubgraphSize = GetGraphSizeVertexEdgeCount(MaxCommonSubGraphVertexEdgeCount.GetMCS(one, two));
			double graphSizeOne = GetGraphSizeVertexEdgeCount(one);
			double graphSizeTwo = GetGraphSizeVertexEdgeCount(two);
			if (maxCommonSubgraphSize == 0.0) return 1;
			return 1 - maxCommonSubgraphSize/Math.Max(graphSizeOne, graphSizeTwo);
		}

		/// <summary>
		/// distance measure proposed by Wallis
		/// </summary>
		/// <param name="one"></param>
		/// <param name="two"></param>
		/// <returns></returns>
		public static double DistWGU4VertexEdgeCount(Graph one, Graph two)
		{
			long mcsSize = GetGraphSizeVertexEdgeCount(MaxCommonSubGraphVertexEdgeCount.GetMCS(one, two));
			if (mcsSize == 0) return 1;
			return 1 - (double) mcsSize/(GetGraphSizeVertexEdgeCount(one) + GetGraphSizeVertexEdgeCount(two) - mcsSize);
		}

		public static double DistWGUVertexEdgeCountExtended(Graph one, Graph two)
		{
			long mcsSize = GetGraphSizeVertexEdgeCount(MaxCommonSubGraphVertexEdgeCount.GetMCS(one, two));
			if (mcsSize == 0) return 1;
			if (mcsSize == GetGraphSizeVertexEdgeCount(one) && mcsSize == GetGraphSizeVertexEdgeCount(two)) return 0;
			return 1 - (double) mcsSize/(GetGraphSizeVertexEdgeCount(one) + GetGraphSizeVertexEdgeCount(two) - 2*mcsSize);
		}

//===========================================================================================
		public static double GetGraphSizeVertexEdgeFrequency(Graph graph)
		{
			return (graph.GetVertexFrequency() + graph.GetEdgeFrequency());
		}

		public static double DistMCS4VertexEdgeFrequency(Graph one, Graph two)
		{
			double maxCommonSubgraphSize = GetGraphSizeVertexEdgeFrequency(MaxCommonSubGraphVertexEdgeFrequency.GetMCS(one, two));
			double graphSizeOne = GetGraphSizeVertexEdgeFrequency(one);
			double graphSizeTwo = GetGraphSizeVertexEdgeFrequency(two);
			if (maxCommonSubgraphSize == 0.0) return 1;
			return 1 - maxCommonSubgraphSize/Math.Max(graphSizeOne, graphSizeTwo);
		}


		/// <summary>
		/// distance measure proposed by Wallis
		/// </summary>
		/// <param name="one"></param>
		/// <param name="two"></param>
		/// <returns></returns>
		public static double DistWGU4VertexEdgeFrequency(Graph one, Graph two)
		{
			double mcsSize = GetGraphSizeVertexEdgeFrequency(MaxCommonSubGraphVertexEdgeFrequency.GetMCS(one, two));
			if (mcsSize == 0.0) return 1;
			return 1 - mcsSize/(GetGraphSizeVertexEdgeFrequency(one) + GetGraphSizeVertexEdgeFrequency(two) - mcsSize);
		}

//=============================================================================================

	}
}